package com.wimcorp.magic.phase;

import java.rmi.RemoteException;
import java.util.HashSet;
import java.util.Set;

import com.wimcorp.magic.abilities.Ability;
import com.wimcorp.magic.players.Player;
import com.wimcorp.magic.spell.Castable;

public class EndingPhase extends Phase {

	private Set<Ability> endStepObservers = new HashSet<Ability>();
	private Set<Ability> cleanUpStepObservers = new HashSet<Ability>();
	private Set<Ability> endOfTurnObservers = new HashSet<Ability>();

	public EndingPhase(Player activePlayer) {
		super(activePlayer);
	}

	public void execute() {
		
		begin();
		if (getStack().size() != 0) {
			activateAbilities();
		}
		cleanup();
		discardExtraCards();
		removeDamage();
		if (getStack().size() != 0) {
			activateAbilities();
		}
		endOfTurn();
	}

	// End

	public void begin() {
		// trigger abilities at beginning of the end step
		for (Ability endStepObserver : endStepObservers) {
			getActivePlayer().cast(endStepObserver);
		}
		if (getStack().size() != 0) {
			// resolve stack
			getStack().resolve();
		}
	}

	// Cleanup

	public void cleanup() {
		// trigger abilities at beginning of the cleanup step
		for (Ability cleanUpStepObserver : cleanUpStepObservers) {
			getActivePlayer().cast(cleanUpStepObserver);
		}
		if (getStack().size() != 0) {
			// resolve stack
			getStack().resolve();
		}
	}

	public void discardExtraCards() {
		while (getActivePlayer().getHand().size() > 7) {
			try {
				getActivePlayerUserInterface().discardExtraCard();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public void removeDamage() {
		getActivePlayer().removeCreatureDamage();
		getActivePlayer().getOpponent().removeCreatureDamage();
	}
	
	public void endOfTurn() {
		// trigger abilities at end of turn
		for (Ability endOfTurnObserver : endOfTurnObservers) {
			getActivePlayer().cast(endOfTurnObserver);
		}
		if (getStack().size() != 0) {
			// resolve stack
			getStack().resolve();
		}
		getActivePlayer().getSummoningPlaines().getSacrifice().reset();
		getActivePlayer().getOpponent().getSummoningPlaines().getSacrifice().reset();
		getActivePlayer().getSummoningPlaines().resetAttackers();
		getActivePlayer().getSummoningPlaines().resetBlockers();
	}

	public void registerEndStepObserver(Ability ability) {
		endStepObservers.add(ability);
	}

	public void unRegisterEndStepObserver(Ability ability) {
		endStepObservers.remove(ability);
	}

	public void registerCleanUpStepObserver(Ability ability) {
		cleanUpStepObservers.add(ability);
	}

	public void unRegisterCleanUpStepObserver(Ability ability) {
		cleanUpStepObservers.remove(ability);
	}
	
	public void registerEndOfTurnObserver(Ability ability) {
		endOfTurnObservers.add(ability);
	}

	public void unRegisterEndOfTurnObserver(Ability ability) {
		endOfTurnObservers.remove(ability);
	}


}
